<!DOCTYPE html>
<html lang="zh">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Canvas连线</title>
	<style media="screen">
		* {
			margin: 0;
			padding: 0;
		}

		#wrap {
			width: 100%;
			background: #000;
		}

		#canvas {
			display: block;
		}
	</style>
</head>

<body>
	<div id="wrap">
		<canvas id="canvas"></canvas>
	</div>

	<script type="text/javascript">
		// 获取窗口宽高
		var h = window.innerHeight,
			w = window.innerWidth;
		document.getElementById('wrap').style.height = h + 'px';

		var con = document.getElementById('canvas');
		// 设置画布
		var c = con.getContext('2d');
		// 给画布设置宽高，此处必须是setAttribute，设置style会导致画出来的图像变形
		con.setAttribute('width', w);
		con.setAttribute('height', h);
		// 监听窗口resize事件，动态设置宽高
		window.onresize = function () {
			h = window.innerHeight;
			w = window.innerWidth;
			document.getElementById('wrap').style.height = h + 'px';
			con.setAttribute('width', w);
			con.setAttribute('height', h);
		}

		// 创建一个圆点对象
		function dot() {
			this.x = Math.random() * w; // X轴坐标，0 - w
			this.y = Math.random() * h; // Y轴坐标， 0 - y
			this.r = Math.random() * 2 + 2; // 圆点半径， 5 - 10
			this.vx = Math.random() * 2 - 1; // X轴加速度，-1 - 1
			this.vy = Math.random() * 2 - 1; // Y轴加速度，-1 - 1
		}

		// 圆点合集
		var dots = [];
		for (var i = 0; i < 200; i++) {
			dots.push(new dot());
		}

		var ex = 0,
			ey = 0;

		function drow() {
			// 鼠标周边的范围
			var mx = ex + 100,
				my = ey + 100,
				nx = ex - 100,
				ny = ey - 100;

			c.clearRect(0, 0, w, h); //清除画布，再开始画下面的圆，否则会连成一条直线
			for (var i = 0; i < dots.length; i++) {
				var dot = dots[i];
				// 开始画圆
				c.beginPath();
				c.arc(dot.x, dot.y, dot.r, 0, 2 * Math.PI); //canvas画圆公式：arc(x,y,r,start,stop)
				c.fillStyle = 'rgba(255,255,255,.3)'; //设置填充颜色
				c.fill(); //填充

				// 匀速运动
				dot.x += dot.vx;
				dot.y += dot.vy;

				//超出屏幕边界时反向运动
				if (dot.x > w || dot.x < 0) {
					dot.vx = dot.vx * -1;
				}
				if (dot.y > w || dot.y < 0) {
					dot.vy = dot.vy * -1;
				}

				// 再次循环，将每个点之间的距离进行计算
				for (var j = 0; j < dots.length; j++) {
					var d = dots[j];
					var s = Math.sqrt(Math.pow((d.x - dot.x), 2) + Math.pow((d.y - dot.y), 2) - d.r / 2 - dot.r / 2); //利用勾股定理计算出距离
					// 如果两点之间的距离小于某个值，就将两点进行连线
					if (s != NaN && s < 100) {
						c.beginPath();
						c.moveTo(dot.x, dot.y); // 线的起点
						c.lineTo(d.x, d.y); // 线的终点
						c.strokeStyle = 'rgba(255,80,120,.2)';
						c.stroke();
					}
					// 如果相邻的点在鼠标位置的某个范围之内,连线
					if (nx < d.x && mx > d.x && ny < d.y && my > d.y && nx < dot.x && mx > dot.x && ny < dot.y && my > dot.y) {
						c.beginPath();
						c.moveTo(dot.x, dot.y); // 线的起点
						c.lineTo(d.x, d.y); // 线的终点
						c.strokeStyle = 'rgba(255,255,255,.5)';
						c.stroke();
					}
				}
			}
			requestAnimationFrame(drow); // 帧动画
		}
		requestAnimationFrame(drow); // 与函数内部的帧动画方法形成一个循环，可以实现定时器的效果
		
		// 获取鼠标位置
		con.onmousemove = function (e) {
			ex = e.x;
			ey = e.y;
		}
	</script>
</body>

</html>
